package viewset.com.recyclewview.threeLayoutManager;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;

/**
 * recyclerview自动滑动到中间位置，参考至SnapHelper的源码分析，重新创建滚动器SmoothScroller并设置到layoutManager中
 */
public class RecyclerViewHelper {
    private RecyclerView mRecyclerView;
    @Nullable
    private OrientationHelper mVerticalHelper;
    @Nullable
    private OrientationHelper mHorizontalHelper;

    private boolean autoCenter; // 是否自动滑动到中间

    private final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {
        boolean mScrolled = false;

        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (newState == 0 && this.mScrolled) {
                this.mScrolled = false;
                if (autoCenter) {
                    snapToTargetExistingView();
                }
            }
        }

        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if (dx != 0 || dy != 0) {
                this.mScrolled = true;
            }

        }
    };


    public RecyclerViewHelper attachToRecyclerView(@Nullable RecyclerView recyclerView) throws IllegalStateException {
        return attachToRecyclerView(recyclerView, false);
    }

    public RecyclerViewHelper attachToRecyclerView(RecyclerView recyclerView, boolean autoCenter) {
        this.autoCenter = autoCenter;
        if (this.mRecyclerView != recyclerView) {
            if (this.mRecyclerView != null) {
                this.destroyCallbacks();
            }

            this.mRecyclerView = recyclerView;
            if (this.mRecyclerView != null) {
                this.setupCallbacks();
            }
        }
        return this;
    }

    void snapToTargetExistingView() {
        if (this.mRecyclerView != null) {
            RecyclerView.LayoutManager layoutManager = this.mRecyclerView.getLayoutManager();
            if (layoutManager != null) {
                View snapView = this.findSnapView(layoutManager);
                if (snapView != null) {
                    int[] snapDistance = this.calculateDistanceToFinalSnap(layoutManager, snapView);
                    if (snapDistance[0] != 0 || snapDistance[1] != 0) {
                        this.mRecyclerView.smoothScrollBy(snapDistance[0], snapDistance[1], new LinearInterpolator());
                    }
                }
            }
        }
    }

    //
    private View findSnapView(RecyclerView.LayoutManager layoutManager) {
        if (layoutManager.canScrollVertically()) {
            return findCenterView(layoutManager, this.getVerticalHelper(layoutManager));
        } else {
            return layoutManager.canScrollHorizontally() ? findCenterView(layoutManager, this.getHorizontalHelper(layoutManager)) : null;
        }
    }


    /**
     * 滚动到中间
     *
     * @param position
     */
    public void smoothScrollToPositionCenter(int position) {
        if (this.mRecyclerView != null) {
            RecyclerView.LayoutManager layoutManager = this.mRecyclerView.getLayoutManager();
            if (layoutManager != null) {
                if (layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider) {
                    View snapView = this.findSnapView(layoutManager, position);
                    float milliseconds;
                    if (snapView != null) { // 判断
                        milliseconds = 600.0F;
                    } else {
                        milliseconds = 100.0F;
                    }
                    final float finalMilliseconds = milliseconds;
                    RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(this.mRecyclerView.getContext()) {
                        protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
                            if (mRecyclerView != null) {
                                int[] snapDistances = calculateDistanceToFinalSnap(mRecyclerView.getLayoutManager(), targetView);
                                int dx = snapDistances[0];
                                int dy = snapDistances[1];
                                int time = this.calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
                                if (time > 0) {
                                    action.update(dx, dy, time, sInterpolator);
                                }
                            }
                        }

                        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                            return finalMilliseconds / (float) displayMetrics.densityDpi;
                        }
                    };

                    smoothScroller.setTargetPosition(position);
                    layoutManager.startSmoothScroll(smoothScroller);
                }

            }
        }
    }

    void setupCallbacks() {
        destroyCallbacks();
        this.mRecyclerView.addOnScrollListener(this.mScrollListener);
    }

    void destroyCallbacks() {
        this.mRecyclerView.removeOnScrollListener(this.mScrollListener);
    }

    /**
     * 插值器
     */
    Interpolator ssInterpolator = new Interpolator() {
        public float getInterpolation(float t) {
            t -= 1.0f;
            return t * t + 1.0f;
        }
    };

    /**
     * 插值器
     */
    Interpolator sInterpolator = new Interpolator() {
        public float getInterpolation(float t) {
            t -= 1.0f;
            return t * t * t * t * t + 1.0f;
        }
    };

    int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View snapView) {
        int[] out = new int[2];
        if (layoutManager.canScrollHorizontally()) {
            out[0] = this.distanceToCenter(layoutManager, snapView, this.getHorizontalHelper(layoutManager));
        } else {
            out[0] = 0;
        }

        if (layoutManager.canScrollVertically()) {
            out[1] = this.distanceToCenter(layoutManager, snapView, this.getVerticalHelper(layoutManager));
        } else {
            out[1] = 0;
        }

        return out;
    }


    private View findSnapView(RecyclerView.LayoutManager layoutManager, int position) {
        return layoutManager.findViewByPosition(position);
    }

    /**
     * 获取itemview的距离中间的距离
     *
     * @param layoutManager
     * @param targetView
     * @param helper
     * @return
     */
    private int distanceToCenter(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView, OrientationHelper helper) {
        int childCenter = helper.getDecoratedStart(targetView) + helper.getDecoratedMeasurement(targetView) / 2;
        int containerCenter;
        if (layoutManager.getClipToPadding()) {
            containerCenter = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;
        } else {
            containerCenter = helper.getEnd() / 2;
        }

        return childCenter - containerCenter;
    }

    @NonNull
    private OrientationHelper getVerticalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
        if (this.mVerticalHelper == null || this.mVerticalHelper.getLayoutManager() != layoutManager) {
            this.mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);
        }

        return this.mVerticalHelper;
    }

    @NonNull
    private OrientationHelper getHorizontalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
        if (this.mHorizontalHelper == null || this.mHorizontalHelper.getLayoutManager() != layoutManager) {
            this.mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
        }

        return this.mHorizontalHelper;
    }

    @Nullable
    private View findCenterView(RecyclerView.LayoutManager layoutManager, OrientationHelper helper) {
        int childCount = layoutManager.getChildCount();
        if (childCount == 0) {
            return null;
        } else {
            View closestChild = null;
            int center;
            if (layoutManager.getClipToPadding()) {
                center = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;
            } else {
                center = helper.getEnd() / 2;
            }

            int absClosest = 2147483647;

            for (int i = 0; i < childCount; ++i) {
                View child = layoutManager.getChildAt(i);
                int childCenter = helper.getDecoratedStart(child) + helper.getDecoratedMeasurement(child) / 2;
                int absDistance = Math.abs(childCenter - center);
                if (absDistance < absClosest) {
                    absClosest = absDistance;
                    closestChild = child;
                }
            }

            return closestChild;
        }
    }
}